﻿using MvCameraControl;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Reflection.PortableExecutable;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Runtime.InteropServices.JavaScript.JSType;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ToolTip;
using String = System.String;

namespace BasicDemo
{
    public partial class BasicDemo : Form
    {
        #region 变量属性
        /// <summary>
        /// 用于根据枚举获取设备列表
        /// </summary>
        readonly DeviceTLayerType enumTLayerType = DeviceTLayerType.MvGigEDevice | DeviceTLayerType.MvUsbDevice
            | DeviceTLayerType.MvGenTLGigEDevice | DeviceTLayerType.MvGenTLCXPDevice | DeviceTLayerType.MvGenTLCameraLinkDevice | DeviceTLayerType.MvGenTLXoFDevice;
        /// <summary>
        /// 设备信息列表
        /// </summary>
        List<IDeviceInfo> deviceInfoList = new List<IDeviceInfo>();
        /// <summary>
        /// 当前设备
        /// </summary>
        IDevice device = null;
        /// <summary>
        /// 是否正在取图
        /// </summary>
        bool isGrabbing = false;        // ch:是否正在取图 | en: Grabbing flag
        /// <summary>
        /// 是否正在录像
        /// </summary>
        bool isRecord = false;          // ch:是否正在录像 | en: Video record flag
        /// <summary>
        /// 接收图像线程
        /// </summary>
        Thread receiveThread = null;    // ch:接收图像线程 | en: Receive image thread
        /// <summary>
        /// 获取到的帧信息, 用于保存图像
        /// </summary>
        private IFrameOut frameForSave;                         // ch:获取到的帧信息, 用于保存图像 | en:Frame for save image
        /// <summary>
        /// 保存图像锁
        /// </summary>
        private readonly object saveImageLock = new object();
        #endregion

        /// <summary>
        /// 海康相机基础演示Demo
        /// </summary>
        public BasicDemo()
        {
            InitializeComponent();

            SDKSystem.Initialize(); // 初始化全局SDK预留调用空间

            RefreshDeviceList(); // 获取设备列表
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        /// <summary>
        /// 显示错误信息
        /// </summary>
        /// <param name="message"></param>
        /// <param name="errorCode"></param>
        private void ShowErrorMsg(string message, int errorCode)
        {
            string errorMsg;
            if (errorCode == 0)
            {
                errorMsg = message;
            }
            else
            {
                errorMsg = message + ": 错误 =" + String.Format("{0:X}", errorCode);
            }

            switch (errorCode)
            {
                case MvError.MV_E_HANDLE: errorMsg += " 错误或无效句柄 "; break;
                case MvError.MV_E_SUPPORT: errorMsg += " \r\n不支持的功能 "; break;
                case MvError.MV_E_BUFOVER: errorMsg += " 缓存已满 "; break;
                case MvError.MV_E_CALLORDER: errorMsg += " 函数调用顺序错误 "; break;
                case MvError.MV_E_PARAMETER: errorMsg += " 不正确的参数 "; break;
                case MvError.MV_E_RESOURCE: errorMsg += " 应用资源失败 "; break;
                case MvError.MV_E_NODATA: errorMsg += " 没有数据 "; break;
                case MvError.MV_E_PRECONDITION: errorMsg += " 前提条件错误，或运行环境已更改 "; break;
                case MvError.MV_E_VERSION: errorMsg += " 版本不匹配 "; break;
                case MvError.MV_E_NOENOUGH_BUF: errorMsg += " 内存不足 "; break;
                case MvError.MV_E_UNKNOW: errorMsg += " 未知错误 "; break;
                case MvError.MV_E_GC_GENERIC: errorMsg += " 一般错误 "; break;
                case MvError.MV_E_GC_ACCESS: errorMsg += " 节点访问条件错误 "; break;
                case MvError.MV_E_ACCESS_DENIED: errorMsg += " 没有权限 "; break;
                case MvError.MV_E_BUSY: errorMsg += " 设备正忙，或网络已断开连接 "; break;
                case MvError.MV_E_NETER: errorMsg += " 网络错误 "; break;
            }

            MessageBox.Show(errorMsg, "提示");
        }

        /// <summary>
        /// 搜索按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bnEnum_Click(object sender, EventArgs e)
        {
            RefreshDeviceList(); // 获取设备列表
        }

        /// <summary>
        /// 获取设备列表
        /// </summary>
        private void RefreshDeviceList()
        {
            // ch:创建设备列表 | en:Create Device List
            cbDeviceList.Items.Clear(); // 清空设备列表
            int nRet = DeviceEnumerator.EnumDevices(enumTLayerType, out deviceInfoList); // 获取设备列表
            if (nRet != MvError.MV_OK)
            {
                ShowErrorMsg("获取设备失败!", nRet);
                return;
            }

            // ch:在窗体列表中显示设备名 | en:Display device name in the form list
            for (int i = 0; i < deviceInfoList.Count; i++) // 循环添加设备名称
            {
                IDeviceInfo deviceInfo = deviceInfoList[i];
                if (deviceInfo.UserDefinedName != "")
                {
                    cbDeviceList.Items.Add(deviceInfo.TLayerType.ToString() + ": " + deviceInfo.UserDefinedName + " (" + deviceInfo.SerialNumber + ")");
                }
                else
                {
                    cbDeviceList.Items.Add(deviceInfo.TLayerType.ToString() + ": " + deviceInfo.ManufacturerName + " " + deviceInfo.ModelName + " (" + deviceInfo.SerialNumber + ")");
                }
            }

            // ch:选择第一项 | en:Select the first item
            if (deviceInfoList.Count != 0)
            {
                cbDeviceList.SelectedIndex = 0;
            }
        }

        /// <summary>
        /// 打开相机控件启用
        /// </summary>
        private void SetCtrlWhenOpen()
        {
            bnOpen.Enabled = false;

            bnClose.Enabled = true;
            bnStartGrab.Enabled = true;
            bnStopGrab.Enabled = false;
            bnContinuesMode.Enabled = true;
            bnContinuesMode.Checked = true;
            bnTriggerMode.Enabled = true;
            cbSoftTrigger.Enabled = false;
            bnTriggerExec.Enabled = false;

            tbExposure.Enabled = true;
            tbGain.Enabled = true;
            tbFrameRate.Enabled = true;
            cbPixelFormat.Enabled = true;
            bnGetParam.Enabled = true;
            bnSetParam.Enabled = true;
        }

        /// <summary>
        /// 打开相机
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bnOpen_Click(object sender, EventArgs e)
        {
            if (deviceInfoList.Count == 0 || cbDeviceList.SelectedIndex == -1)
            {
                ShowErrorMsg("没有设备，请选择", 0);
                return;
            }

            // ch:获取选择的设备信息 | en:Get selected device information
            IDeviceInfo deviceInfo = deviceInfoList[cbDeviceList.SelectedIndex];

            try
            {
                // ch:打开设备 | en:Open device
                device = DeviceFactory.CreateDevice(deviceInfo);
            }
            catch (Exception ex)
            {
                MessageBox.Show("创建设备失败!" + ex.Message);
                return;
            }

            int result = device.Open(); // 打开设备
            if (result != MvError.MV_OK)
            {
                ShowErrorMsg("打开设备失败!", result);
                return;
            }

            //ch: 判断是否为千兆以太网设备 | en: Determine whether it is a GigE device
            if (device is IGigEDevice)
            {
                //ch: 转换为千兆以太网设备 | en: Convert to Gige device
                IGigEDevice gigEDevice = device as IGigEDevice;

                // ch:探测网络最佳包大小(只对千兆以太网相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
                int optionPacketSize;
                result = gigEDevice.GetOptimalPacketSize(out optionPacketSize); // 获取最佳包大小
                if (result != MvError.MV_OK)
                {
                    ShowErrorMsg("警告：获取数据包大小失败!", result);
                }
                else
                {
                    result = device.Parameters.SetIntValue("GevSCPSPacketSize", (long)optionPacketSize); // 设置数据包大小
                    if (result != MvError.MV_OK)
                    {
                        ShowErrorMsg("警告：设置数据包大小失败!", result);
                    }
                }
            }

            // ch:设置采集连续模式 | en:Set Continues Aquisition Mode
            device.Parameters.SetEnumValueByString("AcquisitionMode", "Continuous"); // 设置连续模式
            // 设置为Off会一直触发回调
            device.Parameters.SetEnumValueByString("TriggerMode", "Off"); // 设置触发模式-关

            // ch:控件操作 | en:Control operation
            SetCtrlWhenOpen();

            // ch:获取参数 | en:Get parameters
            bnGetParam_Click(null, null); // 获取相机参数
        }

        /// <summary>
        /// 关闭相机控件按钮设置
        /// </summary>
        private void SetCtrlWhenClose()
        {
            bnOpen.Enabled = true;

            bnClose.Enabled = false;
            bnStartGrab.Enabled = false;
            bnStopGrab.Enabled = false;
            bnContinuesMode.Enabled = false;
            bnTriggerMode.Enabled = false;
            cbSoftTrigger.Enabled = false;
            bnTriggerExec.Enabled = false;

            bnSaveBmp.Enabled = false;
            bnSaveJpg.Enabled = false;
            bnSaveTiff.Enabled = false;
            bnSavePng.Enabled = false;
            tbExposure.Enabled = false;
            tbGain.Enabled = false;
            tbFrameRate.Enabled = false;
            bnGetParam.Enabled = false;
            bnSetParam.Enabled = false;
            cbPixelFormat.Enabled = false;
            bnStartRecord.Enabled = false;
            bnStopRecord.Enabled = false;
        }

        /// <summary>
        /// 关闭相机
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bnClose_Click(object sender, EventArgs e)
        {
            // ch:取流标志位清零 | en:Reset flow flag bit
            if (isGrabbing == true)
            {
                bnStopGrab_Click(sender, e); // 停止采集
            }

            // ch:关闭设备 | en:Close Device
            if (device != null)
            {
                device.Close();
                device.Dispose();
            }

            // ch:控件操作 | en:Control Operation
            SetCtrlWhenClose();
        }

        /// <summary>
        /// 连续模式
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bnContinuesMode_CheckedChanged(object sender, EventArgs e)
        {
            if (bnContinuesMode.Checked)
            {
                // 设置为Off会一直触发回调
                device.Parameters.SetEnumValueByString("TriggerMode", "Off"); // 设置触发模式
                cbSoftTrigger.Enabled = false;
                bnTriggerExec.Enabled = false;
            }
        }

        /// <summary>
        /// 触发模式
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bnTriggerMode_CheckedChanged(object sender, EventArgs e)
        {
            // ch:打开触发模式 | en:Open Trigger Mode
            if (bnTriggerMode.Checked) // 触发模式
            {
                // On-硬件触发 Off-连续触发模式
                device.Parameters.SetEnumValueByString("TriggerMode", "On");

                // ch:触发源选择:0 - Line0; | en:Trigger source select:0 - Line0;
                //           1 - Line1;
                //           2 - Line2;
                //           3 - Line3;
                //           4 - Counter;
                //           7 - Software;
                if (cbSoftTrigger.Checked) // 软件触发
                {
                    device.Parameters.SetEnumValueByString("TriggerSource", "Software"); // 软件触发
                    if (isGrabbing)
                    {
                        bnTriggerExec.Enabled = true;
                    }
                }
                else // 其它触发
                {
                    device.Parameters.SetEnumValueByString("TriggerSource", "Line0"); // 其它触发
                }
                cbSoftTrigger.Enabled = true;
            }
        }

        /// <summary>
        /// 开始采集按钮设置
        /// </summary>
        private void SetCtrlWhenStartGrab()
        {
            bnStartGrab.Enabled = false;
            cbPixelFormat.Enabled = false;
            bnStopGrab.Enabled = true;

            if (bnTriggerMode.Checked && cbSoftTrigger.Checked)
            {
                bnTriggerExec.Enabled = true;
            }

            bnSaveBmp.Enabled = true;
            bnSaveJpg.Enabled = true;
            bnSaveTiff.Enabled = true;
            bnSavePng.Enabled = true;
            bnStartRecord.Enabled = true;
            bnStopRecord.Enabled = false;
        }

        /// <summary>
        /// 图像采集
        /// </summary>
        public void ReceiveThreadProcess()
        {
            int nRet;

            Graphics graphics;   // ch:使用GDI在pictureBox上绘制图像 | en:Display frame using a graphics

            while (isGrabbing)
            {
                IFrameOut frameOut;

                nRet = device.StreamGrabber.GetImageBuffer(1000, out frameOut); // 获取图像缓冲区
                if (MvError.MV_OK == nRet)
                {
                    if (isRecord) // 用于录像
                    {
                        device.VideoRecorder.InputOneFrame(frameOut.Image); // 输入一帧图像-录像用的
                    }

                    lock (saveImageLock) // 用于保存图像
                    {
                        try
                        {
                            frameForSave = frameOut.Clone() as IFrameOut; // 克隆图像
                        }
                        catch (Exception e)
                        {
                            MessageBox.Show("IFrameOut.克隆失败, " + e.Message);
                            return;
                        }
                    }

#if !GDI_RENDER
                    device.ImageRender.DisplayOneFrame(pictureBox1.Handle, frameOut.Image); // 显示一帧图像
#else
                    // 使用GDI绘制图像
                    try
                    {
                        using (Bitmap bitmap = frameOut.Image.ToBitmap())
                        {
                            if (graphics == null)
                            {
                                graphics = pictureBox1.CreateGraphics();
                            }

                            Rectangle srcRect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
                            Rectangle dstRect = new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Height);
                            graphics.DrawImage(bitmap, dstRect, srcRect, GraphicsUnit.Pixel);
                        }
                    }
                    catch (Exception e)
                    {
                        device.StreamGrabber.FreeImageBuffer(frameOut);
                        MessageBox.Show(e.Message);
                        return;
                    }
#endif


                    device.StreamGrabber.FreeImageBuffer(frameOut); // 释放图像缓存
                }
                else
                {
                    if (bnTriggerMode.Checked)
                    {
                        Thread.Sleep(5);
                    }
                }
            }
        }

        /// <summary>
        /// 开始采集
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bnStartGrab_Click(object sender, EventArgs e)
        {
            try
            {
                // ch:标志位置位true | en:Set position bit true
                isGrabbing = true;

                receiveThread = new Thread(ReceiveThreadProcess);
                receiveThread.Start();
            }
            catch (Exception ex)
            {
                MessageBox.Show("启动线程失败!, " + ex.Message);
                throw;
            }

            // ch:开始采集 | en:Start Grabbing
            int result = device.StreamGrabber.StartGrabbing(); // 开始采集
            if (result != MvError.MV_OK)
            {
                isGrabbing = false;
                receiveThread.Join();
                ShowErrorMsg("开始抓取失败!", result);
                return;
            }

            // ch:控件操作 | en:Control Operation
            SetCtrlWhenStartGrab();
        }

        /// <summary>
        /// 软件触发
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cbSoftTrigger_CheckedChanged(object sender, EventArgs e)
        {
            if (cbSoftTrigger.Checked)
            {
                // ch:触发源设为软触发 | en:Set trigger source as Software
                device.Parameters.SetEnumValueByString("TriggerSource", "Software"); // 软件触发
                if (isGrabbing)
                {
                    bnTriggerExec.Enabled = true;
                }
            }
            else
            {
                device.Parameters.SetEnumValueByString("TriggerSource", "Line0"); 
                bnTriggerExec.Enabled = false;
            }
        }

        /// <summary>
        /// 触发一次
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bnTriggerExec_Click(object sender, EventArgs e)
        {
            // ch:触发命令 | en:Trigger command
            int result = device.Parameters.SetCommandValue("TriggerSoftware");
            if (result != MvError.MV_OK)
            {
                ShowErrorMsg("触发软件失败!", result);
            }
        }

        /// <summary>
        /// 停止采集按钮设置
        /// </summary>
        private void SetCtrlWhenStopGrab()
        {
            bnStartGrab.Enabled = true;
            cbPixelFormat.Enabled = true;
            bnStopGrab.Enabled = false;
            bnTriggerExec.Enabled = false;

            bnSaveBmp.Enabled = false;
            bnSaveJpg.Enabled = false;
            bnSaveTiff.Enabled = false;
            bnSavePng.Enabled = false;
            bnStartRecord.Enabled = false;
            bnStopRecord.Enabled = false;
        }

        /// <summary>
        /// 停止采集
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bnStopGrab_Click(object sender, EventArgs e)
        {
            if (isRecord)
            {
                bnStopRecord_Click(sender, e); // 停止录像
            }

            // ch:标志位设为false | en:Set flag bit false
            isGrabbing = false;
            receiveThread.Join(); // 停止采集线程

            // ch:停止采集 | en:Stop Grabbing
            int result = device.StreamGrabber.StopGrabbing(); // 停止采集
            if (result != MvError.MV_OK)
            {
                ShowErrorMsg("停止抓取失败!", result);
            }

            // ch:控件操作 | en:Control Operation
            SetCtrlWhenStopGrab();
        }

        /// <summary>
        /// 保存图像
        /// </summary>
        /// <param name="imageFormatInfo"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        private int SaveImage(ImageFormatInfo imageFormatInfo)
        {
            if (frameForSave == null)
            {
                throw new Exception("没有可用图像");
            }

            string imagePath = $"Image_w{frameForSave.Image.Width.ToString()}_h{frameForSave.Image.Height.ToString()}_fn{frameForSave.FrameNum.ToString()}.{imageFormatInfo.FormatType.ToString()}";

            lock (saveImageLock)
            {
                return device.ImageSaver.SaveImageToFile(imagePath, frameForSave.Image, imageFormatInfo, CFAMethod.Equilibrated); // 保存图像
            }
        }

        /// <summary>
        /// 保存Bmp图像
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bnSaveBmp_Click(object sender, EventArgs e)
        {
            int result;

            try
            {
                ImageFormatInfo imageFormatInfo = new ImageFormatInfo(); // 图像格式信息
                imageFormatInfo.FormatType = ImageFormatType.Bmp; // 设置图像格式

                result = SaveImage(imageFormatInfo); // 保存图像
                if (result != MvError.MV_OK)
                {
                    ShowErrorMsg("保存图像失败!", result);
                    return;
                }
                else
                {
                    ShowErrorMsg("保存图像成功!", 0);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("保存图像失败, " + ex.Message);
                return;
            }
        }

        /// <summary>
        /// 保存Jpg图像
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bnSaveJpg_Click(object sender, EventArgs e)
        {
            int result;

            try
            {
                ImageFormatInfo imageFormatInfo; // 图像信息
                imageFormatInfo.FormatType = ImageFormatType.Jpeg; // 设置图像格式
                imageFormatInfo.JpegQuality = 80; // 图像质量

                result = SaveImage(imageFormatInfo); // 保存图像
                if (result != MvError.MV_OK)
                {
                    ShowErrorMsg("保存图像失败!", result);
                    return;
                }
                else
                {
                    ShowErrorMsg("保存图像成功!", 0);
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show("保存图像失败, " + ex.Message);
                return;
            }
        }

        /// <summary>
        /// 保存Png图像
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bnSavePng_Click(object sender, EventArgs e)
        {
            int result;

            try
            {
                ImageFormatInfo imageFormatInfo = new ImageFormatInfo(); // 图像信息
                imageFormatInfo.FormatType = ImageFormatType.Png; // 设置图像格式

                result = SaveImage(imageFormatInfo); // 保存图像
                if (result != MvError.MV_OK)
                {
                    ShowErrorMsg("保存图像失败!", result);
                    return;
                }
                else
                {
                    ShowErrorMsg("保存图像成功!", 0);
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show("保存图像失败, " + ex.Message);
                return;
            }
        }

        /// <summary>
        /// 保存Tiff图像
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bnSaveTiff_Click(object sender, EventArgs e)
        {
            int result;
            try
            {
                ImageFormatInfo imageFormatInfo = new ImageFormatInfo(); // 图像信息
                imageFormatInfo.FormatType = ImageFormatType.Tiff; // 设置图像格式

                result = SaveImage(imageFormatInfo); // 保存图像
                if (result != MvError.MV_OK)
                {
                    ShowErrorMsg("保存图像失败!", result);
                    return;
                }
                else
                {
                    ShowErrorMsg("保存图像成功!", 0);
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show("保存图像失败, " + ex.Message);
                return;
            }
        }

        /// <summary>
        /// ch:获取触发模式 | en:Get Trigger Mode
        /// </summary>
        private void GetTriggerMode()
        {
            IEnumValue enumValue;
            int result = device.Parameters.GetEnumValue("TriggerMode", out enumValue); // 获取触发模式
            if (result == MvError.MV_OK)
            {
                if (enumValue.CurEnumEntry.Symbolic == "On") // 触发模式开
                {
                    bnTriggerMode.Checked = true;
                    bnContinuesMode.Checked = false;

                    result = device.Parameters.GetEnumValue("TriggerSource", out enumValue); // 获取触发源
                    if (result == MvError.MV_OK)
                    {
                        if (enumValue.CurEnumEntry.Symbolic == "TriggerSoftware")
                        {
                            cbSoftTrigger.Enabled = true;
                            cbSoftTrigger.Checked = true;
                            if (isGrabbing)
                            {
                                bnTriggerExec.Enabled = true;
                            }
                        }
                    }
                }
                else
                {
                    bnContinuesMode.Checked = true;
                    bnTriggerMode.Checked = false;
                }
            }
        }

        /// <summary>
        /// 获取相机参数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bnGetParam_Click(object sender, EventArgs e)
        {

            GetTriggerMode();

            IFloatValue floatValue;
            int result = device.Parameters.GetFloatValue("ExposureTime", out floatValue); // 获取曝光时间
            if (result == MvError.MV_OK)
            {
                tbExposure.Text = floatValue.CurValue.ToString("F1");
            }

            result = device.Parameters.GetFloatValue("Gain", out floatValue); // 获取增益
            if (result == MvError.MV_OK)
            {
                tbGain.Text = floatValue.CurValue.ToString("F1");
            }

            result = device.Parameters.GetFloatValue("ResultingFrameRate", out floatValue); // 获取帧率
            if (result == MvError.MV_OK)
            {
                tbFrameRate.Text = floatValue.CurValue.ToString("F1");
            }

            cbPixelFormat.Items.Clear();
            IEnumValue enumValue;
            result = device.Parameters.GetEnumValue("PixelFormat", out enumValue); // 获取像素格式
            if (result == MvError.MV_OK)
            {
                foreach (var item in enumValue.SupportEnumEntries) // 循环添加帧率
                {
                    cbPixelFormat.Items.Add(item.Symbolic);
                    if (item.Symbolic == enumValue.CurEnumEntry.Symbolic)
                    {
                        cbPixelFormat.SelectedIndex = cbPixelFormat.Items.Count - 1;
                    }
                }
            }
        }

        /// <summary>
        /// 设置相机参数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bnSetParam_Click(object sender, EventArgs e)
        {
            try
            {
                float.Parse(tbExposure.Text);
                float.Parse(tbGain.Text);
                float.Parse(tbFrameRate.Text);
            }
            catch
            {
                ShowErrorMsg("请输入正确的类型!", 0);
                return;
            }

            device.Parameters.SetEnumValue("ExposureAuto", 0); // 设置曝光时间自动
            int result = device.Parameters.SetFloatValue("ExposureTime", float.Parse(tbExposure.Text)); // 设置曝光时间
            if (result != MvError.MV_OK)
            {
                ShowErrorMsg("设置曝光时间失败!", result);
            }

            device.Parameters.SetEnumValue("GainAuto", 0); // 设置增益自动
            result = device.Parameters.SetFloatValue("Gain", float.Parse(tbGain.Text)); // 设置增益
            if (result != MvError.MV_OK)
            {
                ShowErrorMsg("设置增益失败!", result);
            }

            result = device.Parameters.SetBoolValue("AcquisitionFrameRateEnable", true); // 设置采集帧启用
            if (result != MvError.MV_OK)
            {
                ShowErrorMsg("设置采集帧启用失败!", result);
            }
            else
            {
                result = device.Parameters.SetFloatValue("AcquisitionFrameRate", float.Parse(tbFrameRate.Text)); // 设置采集帧率
                if (result != MvError.MV_OK)
                {
                    ShowErrorMsg("设置采集帧率失败!", result);
                }
            }
        }

        /// <summary>
        /// ch:程序关闭事件，释放SDK资源 | en:FormClosing, dispose SDK resources
        /// </summary>
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            bnClose_Click(sender, e);

            SDKSystem.Finalize(); // 释放SDK预留缓存
        }

        /// <summary>
        /// 开始录像按钮设置
        /// </summary>
        private void SetCtrlWhenStartRecord()
        {
            bnStartRecord.Enabled = false;
            bnStopRecord.Enabled = true;
        }

        /// <summary>
        /// 开始录像
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bnStartRecord_Click(object sender, EventArgs e)
        {
            if (false == isGrabbing)
            {
                ShowErrorMsg("未开始采集", 0);
                return;
            }

            IIntValue intValue;
            IEnumValue enumValue;

            uint width;
            uint height;
            MvGvspPixelType pixelType;

            int result;

            result = device.Parameters.GetIntValue("Width", out intValue); 
            if (result != MvError.MV_OK)
            {
                ShowErrorMsg("获取宽度失败!", result);
                return;
            }
            width = (uint)intValue.CurValue;

            result = device.Parameters.GetIntValue("Height", out intValue);
            if (result != MvError.MV_OK)
            {
                ShowErrorMsg("获取高度失败!", result);
                return;
            }
            height = (uint)intValue.CurValue;

            result = device.Parameters.GetEnumValue("PixelFormat", out enumValue);
            if (result != MvError.MV_OK)
            {
                ShowErrorMsg("获取像素格式失败!", result);
                return;
            }
            pixelType = (MvGvspPixelType)enumValue.CurEnumEntry.Value;

            // ch:开始录像 | en:Start record
            RecordParam recordParam;
            recordParam.Width = width;
            recordParam.Height = height;
            recordParam.PixelType = pixelType;
            recordParam.FrameRate = float.Parse(tbFrameRate.Text);
            recordParam.BitRate = 1000;
            recordParam.FormatType = VideoFormatType.AVI;

            result = device.VideoRecorder.StartRecord("./Record.avi", recordParam); // 开始录像
            if (result != MvError.MV_OK)
            {
                ShowErrorMsg("开始录像失败!", result);
                return;
            }

            isRecord = true;

            SetCtrlWhenStartRecord(); 
        }

        /// <summary>
        /// 停止录像设置按钮
        /// </summary>
        private void SetCtrlWhenStopRecord()
        {
            bnStartRecord.Enabled = true;
            bnStopRecord.Enabled = false;
        }

        /// <summary>
        /// 停止录像
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bnStopRecord_Click(object sender, EventArgs e)
        {
            if (false == isGrabbing)
            {
                ShowErrorMsg("未开始采集", 0);
                return;
            }

            int result = device.VideoRecorder.StopRecord(); // 停止录像
            if (result != MvError.MV_OK)
            {
                ShowErrorMsg("停止录像失败!", result);
            }

            isRecord = false;
            SetCtrlWhenStopRecord();
        }

        /// <summary>
        /// 设置像素格式
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cbPixelFormat_SelectionChangeCommitted(object sender, EventArgs e)
        {
            int result = device.Parameters.SetEnumValueByString("PixelFormat", cbPixelFormat.Text); // 设置像素格式
            if (result != MvError.MV_OK)
            {
                ShowErrorMsg("Set PixelFormat failed!", result); // 设置像素格式失败
            }
        }
    }
}
